#include <time.h>
#include "seqiot.h"
#include "sqlite.h"
#include "redis.h"

static value_id_t id = {-1, -1, -1, -1};
static int cat_id = -1;
static int min_tag = 0, max_tag = 0xffff;

void print_device_segment(device_t *device, segment_e seg_id) {
    int rc, i;

    vector_t key_list = vector_initializer;
    vector_t val_list = vector_initializer;

    vector_t *tag_list = &device->_product->thing_model[seg_id];
    for (i = 0; i < vector_size(tag_list); ++i) {
        thing_model_t *tag = vector_get(tag_list, i);
        if (-1 != cat_id && tag->catalog != cat_id) continue;

        if (tag->super.id >= min_tag && tag->super.id <= max_tag) {
            vector_add(&key_list, tag);
        }
    }

    printf("\n==========(id=%d,name=%s,seg=%d)==========\n", device->super.id, device->super.name, seg_id);
    rc = redis_get_values(device, &key_list, &val_list);
    if (rc < 0) {
        goto end;
    }

    time_t curr = time(NULL);

    for (i = 0; i < vector_size(&key_list); ++i) {
        thing_model_t *key = vector_get(&key_list, i);
        value_t *val = vector_get(&val_list, i);

        printf("tag=%04x(%5d)", key->super.id, key->super.id);

        if (0 != val->timestamp) {
            struct tm _tm;
            localtime_r(&val->timestamp, &_tm);
            printf(", ts=%02d:%02d:%02d", _tm.tm_hour, _tm.tm_min, _tm.tm_sec);

            int diff = curr - val->timestamp;
            int days = diff / (24 * 60 * 60);
            int hours = (diff / (60 * 60)) % 24;
            int mins = (diff / 60) % 60;
            int secs = diff % 60;
            if (days > 0) {
                printf("(%02dd.%02dh)", days, hours);
            } else if (hours > 0) {
                printf("(%02dh.%02dm)", hours, mins);
            } else if (mins > 0) {
                printf("(%02dm.%02ds)", mins, secs);
            } else {
                printf("(00m.%02ds)", secs);
            }
        }

        printf(", hex=0x%016llx, val=%f, name=%s\n", val->_val, val->value, key->super.name);
    }

    end:
    vector_clear(&key_list);
    vector_foreach(&val_list, (vector_foreach_callback) value_free);
    vector_clear(&val_list);
}

void print_device(device_t *device) {
    int i;

    for (i = 0; i < sizeof(device->_product->thing_model) / sizeof(device->_product->thing_model[0]); ++i) {
        if (-1 != id.seg_id && i != id.seg_id) continue;

        vector_t *tag_list = &device->_product->thing_model[i];
        if (vector_size(tag_list)) {
            print_device_segment(device, i);
        }
    }
}

int main(int argc, char *argv[]) {
    int i, j;

    for (i = 1; i < argc; ++i) {
        if (!strcmp("-c", argv[i])) {
            id.chn_id = atoi(argv[++i]);
        } else if (!strcmp("-d", argv[i])) {
            id.dev_id = atoi(argv[++i]);
        } else if (!strcmp("-s", argv[i])) {
            id.seg_id = atoi(argv[++i]);
        } else if (!strcmp("-c", argv[i])) {
            cat_id = atoi(argv[++i]);
        } else if (!strcmp("--min", argv[i])) {
            min_tag = atoi(argv[++i]);
        } else if (!strcmp("--max", argv[i])) {
            max_tag = atoi(argv[++i]);
        } else {
            printf("usage: %s [-c <channel>] [-d <device>] [-s <segment>] [-c <catalog>] [--min <min_tag>] [--max <max_tag>]\n",
                   argv[0]);
            return EXIT_SUCCESS;
        }
    }

    log_init();

    seqiot_t *seqiot = seqiot_new();
    read_config(seqiot, NULL, 0, -1);

    if (!redis_open(seqiot->local_address)) {
        return EXIT_FAILURE;
    }
    for (i = 0; i < vector_size(&seqiot->channels); ++i) {
        channel_t *channel = vector_get(&seqiot->channels, i);
        if (-1 != id.chn_id && channel->super.id != id.chn_id) continue;

        for (j = 0; j < vector_size(&channel->devices); ++j) {
            device_t *device = vector_get(&channel->devices, j);
            if (-1 != id.dev_id && device->super.id != id.dev_id) continue;
            if (channel->super.id == device->channel)
                print_device(device);
        }
    }
    redis_close();

    seqiot_free(seqiot);
    log_fini();

    return EXIT_SUCCESS;
}
